package ar.uade.fain.ai.tpo.dao;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;
import java.util.Set;

import ar.uade.fain.ai.tpo.model.Categoria;
import ar.uade.fain.ai.tpo.model.Comida;
import ar.uade.fain.ai.tpo.model.Receta;
import ar.uade.fain.ai.tpo.model.Seccion;

public class ComidaDAO extends CacheDAOSupport<Comida> {

	private static final String DELETE_COMIDA = 
			"UPDATE delivery.dbo.COMIDA SET ACTIVO = 0 WHERE IDCOMIDA = ?";

	private static final String SELECT_BY_ID = 
			"SELECT * FROM delivery.dbo.COMIDA " +
			"WHERE IDCOMIDA = ? and activo = 1";
	
	private static final String INSERT_COMIDA = 
			"INSERT INTO delivery.dbo.COMIDA " +
			"(idcomida,idreceta,idcategoria,idseccion,nombre,activo) " +
			"VALUES (?,?,?,?,?,1)";
	
	private static final String GET_NEXT_ID = 
			"SELECT ISNULL(MAX(IDCOMIDA),0)+1 AS ID FROM DELIVERY.DBO.COMIDA";
	
	private RecetaDAO recetaDAO;
	private CategoriaDAO categoriaDAO;
	
	public ComidaDAO() {
		super();
	}

	public CategoriaDAO getCategoriaDAO() {
		return categoriaDAO;
	}

	public void setCategoriaDAO(CategoriaDAO categoriaDAO) {
		this.categoriaDAO = categoriaDAO;
	}
	
	public RecetaDAO getRecetaDAO() {
		return recetaDAO;
	}

	public void setRecetaDAO(RecetaDAO recetaDAO) {
		this.recetaDAO = recetaDAO;
	}
	
	public Comida getByID(final Long id) {
		final Set<Comida> enCache = buscarEnCache(new Selector<Comida>() {
			@Override
			public boolean aceptar(Comida entidad) {
				return entidad.getId().equals(id);
			}
		});
		if (enCache.isEmpty()) {
			return load(id);
		} else {
			return enCache.iterator().next();
		}
	}

	private Comida load(final Long id) {
		final List<Comida> comidas = database().select(SELECT_BY_ID, 
			id, new RowMapper<Comida>() {
			@Override
			public Comida map(ResultSet rs)
					throws SQLException {
				final Comida comida = new Comida();
				comida.setId(rs.getLong("idcomida"));
				comida.setNombre(rs.getString("nombre"));
				final Receta receta = 
						getRecetaDAO().buscarPorId(rs.getLong("idreceta"));
				comida.setReceta(receta);
				final Categoria categoria = 
						getCategoriaDAO().buscarPorId(rs.getLong("idcategoria"));
				comida.setCategoria(categoria);
				final Seccion seccion = new Seccion(
						rs.getLong("idseccion"), "<not loaded>");
				comida.setSeccion(seccion);
				return comida;
			}
		});
		final Comida result = comidas.isEmpty() ? null : comidas.get(0);
		agregarACache(result);
		return result;
	}
	
	
	public void guardar(final Comida comida) {
		final Long nextId = database().selectNextId(GET_NEXT_ID);
		database().insert(INSERT_COMIDA, new ParameterSetter() {
			@Override
			public void setParametros(final PreparedStatement statement) 
					throws SQLException {
				statement.setLong(1, nextId);
				statement.setLong(2, comida.getReceta().getId());
				statement.setLong(3, comida.getCategoria().getId());
				statement.setLong(4, comida.getSeccion().getId());
				statement.setString(5, comida.getNombre());
			}
		});
		comida.setId(nextId);
		agregarACache(comida);
	}
	
	public void eliminar(final Long id) {
		database().update(DELETE_COMIDA, ParameterSetter.Factory.idOnly(id));
		quitarDelCache(new Selector<Comida>() {
			@Override
			public boolean aceptar(Comida entidad) {
				return entidad.getId().equals(id);
			}
		});
	}

}
